package com.bj.zspace.sentinel.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.bj.zspace.sentinel.service.HelloWorldService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collectors;

@RestController
public class HellWorldController {

    @Resource
    private HelloWorldService helloWorldService;

    @GetMapping(value = "/hello")
    @SentinelResource(value = "helloWorld")
    public String helloWorld(){
        return "hello world";
    }

    @GetMapping(value = "/cluster")
    public String cluster(){
        return helloWorldService.testCluster();
    }
    @GetMapping(value = "/spho")
    public String SphO(){
        if (SphO.entry("resource1")) {
            try {
                // business logic
                return "spho";
            } finally {
                SphO.exit(); // must exit()
            }
        } else {
            return "fail";
        }
    }
    @GetMapping(value = "/sphu")
    public String SphU() throws BlockException {
        Entry entry = null;
        try {
            entry = SphU.entry("pressure_test");
            //business logic
        } catch (BlockException e) {
            // 被限流了业务处理
            throw e;
        }finally {
            if(entry != null){
                entry.exit();
            }
        }
        return "SphU";
    }

    @GetMapping(value = "/urlCluster")
    public String urlCluster(){
        return "url cluster";
    }

    @GetMapping(value = "/pressure")
    public String pressure(){
        long startTime = System.currentTimeMillis();
        ConcurrentHashMap<Long, LongAdder> success = new ConcurrentHashMap<>(10000);
        ConcurrentHashMap<Long, LongAdder> error = new ConcurrentHashMap<>(10000);
        for (int i = 0; i < 1000; i++) {
           new Thread(() -> doPress(startTime, success ,error), "press-tread-1") .start();
        }

        new Thread(() -> {
            while (true) {

                System.out.println("--------------------");
                List<Long> sucKeys = success.keySet().stream().collect(Collectors.toList());
                sucKeys.sort(Long::compareTo);
                for (Long sucKey : sucKeys) {
                    System.out.println(sucKey + "," + success.get(sucKey));
                }
                System.out.println("--------------------");
                List<Long> errorKeys = error.keySet().stream().collect(Collectors.toList());
                errorKeys.sort(Long::compareTo);
                for (Long errorKey : errorKeys) {
                    System.out.println(errorKey + "," + error.get(errorKey));
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        return "ok";

    }


    private void doPress(long startTime, ConcurrentHashMap<Long, LongAdder> success, ConcurrentHashMap<Long, LongAdder> error) {
        while (true) {
            Entry entry = null;
            try {
                entry = SphU.entry("pressure_test");
                //business logic
            } catch (BlockException e) {
                // 被限流了业务处理
                Long key = System.currentTimeMillis() / 1000;
                LongAdder errorDefault = error.getOrDefault(key, new LongAdder());
                errorDefault.increment();
                error.put(key, errorDefault);
            }finally {
                Long key = System.currentTimeMillis() / 1000;
                LongAdder successDefault = success.getOrDefault(key, new LongAdder());
                successDefault.increment();
                success.put(key, successDefault);
                if(entry != null){
                    entry.exit();
                }
            }
            if((System.currentTimeMillis() - startTime) > 60 * 1000) {
                break;
            }

        }

    }

}
